#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>           //画家类
#include <QPropertyAnimation> //动画
#include <QRandomGenerator>   //随机数

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 设置界面标题 图标 固定大小 位置
    this->setWindowTitle("咩了个咩");
    this->setWindowIcon(QIcon(":/res/title.png"));
    this->setFixedSize(main_width, main_heigth);
    this->move((1920 - main_width) * 0.5 * 0.75, 0);

    // 数组初始化
    for (int i = 0; i < (sizeof(cardArr) / sizeof(cardArr[0])); i++)
        cardArr[i] = nullptr;
    for (int i = 0; i < (group_num * 3); i++)
        allCardArr[i] = nullptr;
    // 生成卡片的种类
    for (int i = 0; i < 7; i++)
    {
        static int buildCardCount = 0;
        if (i < (group_num % 7))
            for (int j = 0; j < ((group_num / 7 + 1) * 3); j++)
                cardGroup[buildCardCount++] = i + 1;
        else
            for (int j = 0; j < ((group_num / 7) * 3); j++)
                cardGroup[buildCardCount++] = i + 1;
    }
    // 打乱数组数据(随机生成下标 然后和当前下标的数交换)
    for (int i = 0; i < (group_num * 3); i++)
    {
        int temp;
        int randomNum;
        randomNum = QRandomGenerator::global()->bounded(group_num * 3);
        temp = cardGroup[i];
        cardGroup[i] = cardGroup[randomNum];
        cardGroup[randomNum] = temp;
    }
    // 生成卡片
    for (int i = 1; i <= 5; i++)
    {
        static int cardCount = 0;
        // 总共五个部分（层）
        switch (i)
        {
        case 1:
            for (int m = 0; m < 6; m++)
            {
                if (m == 1)
                    continue;
                for (int n = 0; n < 5; n++)
                {
                    Card *card = new Card(cardGroup[cardCount], 0);
                    card->setParent(this);
                    // 给卡片属性赋值
                    if ((m == 0 || m == 5) && n == 4)
                        card->upCardNum = 1;
                    else if (m == 0 || m == 5)
                        card->upCardNum = 2;
                    else if (n == 4)
                        card->upCardNum = 2;
                    else
                        card->upCardNum = 4;
                    // 卡片位置
                    card->move(64 + card->width() * m, 130 + n * (card->height() - 1));
                    // 记录到数组里
                    allCardArr[cardCount++] = card;
                    // 连接点击
                    this->cardConnect(card);
                }
            }
            break;
        case 2:
            for (int m = 0; m < 5; m++)
            {
                for (int n = 0; n < 5; n++)
                {
                    Card *card = new Card(cardGroup[cardCount], 0);
                    card->setParent(this);
                    // 给卡片属性赋值
                    if ((m == 0 || m == 4) && n == 4)
                        card->upCardNum = 1;
                    else if (m == 0 || m == 4)
                        card->upCardNum = 2;
                    else if (n == 4)
                        card->upCardNum = 2;
                    else
                        card->upCardNum = 4;

                    if (m < 2)
                    {
                        if (n == 0)
                            card->lowCardNumArr[0] = m * 5;
                        else
                        {
                            card->lowCardNumArr[0] = m * 5 + n - 1;
                            card->lowCardNumArr[1] = m * 5 + n;
                        }
                    }
                    else
                    {
                        if (n == 0)
                        {
                            card->lowCardNumArr[0] = (m - 1) * 5;
                            card->lowCardNumArr[1] = m * 5;
                        }
                        else
                        {
                            card->lowCardNumArr[0] = (m - 1) * 5 + n - 1;
                            card->lowCardNumArr[1] = (m - 1) * 5 + n;
                            card->lowCardNumArr[2] = m * 5 + n - 1;
                            card->lowCardNumArr[3] = m * 5 + n;
                        }
                    }
                    // 卡片位置
                    card->move(90 + card->width() * m, 102 + n * (card->height() - 1));
                    // 记录到数组里
                    allCardArr[cardCount++] = card;
                    // 连接点击
                    this->cardConnect(card);
                }
            }
            break;
        case 3:
            for (int m = 0; m < 4; m++)
            {
                for (int n = 0; n < 5; n++)
                {
                    Card *card = new Card(cardGroup[cardCount], 1);
                    card->setParent(this);
                    // 给卡片属性赋值
                    if (n == 0)
                    {
                        card->lowCardNumArr[0] = 25 + m * 5;
                        card->lowCardNumArr[1] = 25 + (m + 1) * 5;
                    }
                    else
                    {
                        card->lowCardNumArr[0] = 25 + m * 5 + n - 1;
                        card->lowCardNumArr[1] = 25 + m * 5 + n;
                        card->lowCardNumArr[2] = 25 + (m + 1) * 5 + n - 1;
                        card->lowCardNumArr[3] = 25 + (m + 1) * 5 + n;
                    }
                    // 卡片位置
                    card->move(116 + card->width() * m, 74 + n * (card->height() - 1));
                    // 记录到数组里
                    allCardArr[cardCount++] = card;
                    // 连接点击
                    this->cardConnect(card);
                }
            }
            break;
        case 4:
            for (int m = 0; m < 6; m++)
            {
                Card *card = new Card(cardGroup[cardCount], 0);
                card->setParent(this);
                // 给卡片属性赋值
                card->upCardNum = 1;
                // 卡片位置
                card->move(64 + card->width() * m, 438);
                // 记录到数组里
                allCardArr[cardCount++] = card;
                // 连接点击
                this->cardConnect(card);
            }
            for (int m = 0; m < 6; m++)
            {
                Card *card = new Card(cardGroup[cardCount], 1);
                card->setParent(this);
                // 给卡片属性赋值
                card->lowCardNumArr[0] = 70 + m;
                // 卡片位置
                card->move(64 + card->width() * m, 410);
                // 记录到数组里
                allCardArr[cardCount++] = card;
                // 连接点击
                this->cardConnect(card);
            }
            break;
        case 5:
            for (int m = 0; m < 9; m++)
            {
                Card *card = new Card(cardGroup[cardCount], 0);
                card->setParent(this);
                // 给卡片属性赋值
                card->upCardNum = 1;
                if (m != 0)
                    card->lowCardNumArr[0] = 82 + m - 1;
                // 卡片位置
                card->move(50 + 10 * m, 520);
                // 记录到数组里
                allCardArr[cardCount++] = card;
                // 连接点击
                this->cardConnect(card);
            }
            for (int m = 0; m < 9; m++)
            {
                Card *card = new Card(cardGroup[cardCount], 0);
                card->setParent(this);
                // 给卡片属性赋值
                card->upCardNum = 1;
                if (m != 0)
                    card->lowCardNumArr[0] = 91 + m - 1;
                // 卡片位置
                card->move(338 - 10 * m, 520);
                // 记录到数组里
                allCardArr[cardCount++] = card;
                // 连接点击
                this->cardConnect(card);
            }
            for (int m = 0; m < 2; m++)
            {
                Card *card = new Card(cardGroup[cardCount], 1);
                card->setParent(this);
                // 给卡片属性赋值
                if (m == 0)
                    card->lowCardNumArr[0] = 90;
                else
                    card->lowCardNumArr[0] = 99;
                // 卡片位置
                if (m == 0)
                    card->move(50 + 10 * 9, 520);
                else
                    card->move(338 - 10 * 9, 520);
                // 记录到数组里
                allCardArr[cardCount++] = card;
                // 连接点击
                this->cardConnect(card);
            }
            break;
        }
    }
}
// 执行每个卡片的连接connect
void MainWindow::cardConnect(Card *card)
{
    connect(card, &Card::clicked, [=]()
            {
                // 置顶层
                card->raise();
                // 点击标志
                card->isClicked = true;
                // 判断是否有三消存在（不执行操作）
                int repeat_count = 0;
                int allcard_count = 0;
                for (int i = 0; cardArr[i] != nullptr; i++)
                {
                    if (cardArr[i]->nums == card->nums)
                        repeat_count++;
                    allcard_count++;
                }
                if (repeat_count < 2)
                {
                    // 判断此时栏里的数量 若有六个则游戏失败
                    if (allcard_count == 6)
                        this->gameOver(); // 游戏失败 传入默认值为0
                }
                // 根据 下层卡片的数组下标 判断是否将下层的显示
                for (int i = 0; (card->lowCardNumArr[i] != -1) && (i < 4); i++)
                {
                    if (--(allCardArr[card->lowCardNumArr[i]]->upCardNum) == 0)
                    {
                        QString str = QString(":/res/00%1.png").arg(allCardArr[card->lowCardNumArr[i]]->nums);
                        allCardArr[card->lowCardNumArr[i]]->setIcon(QIcon(str));
                        allCardArr[card->lowCardNumArr[i]]->isUpper = true;
                    }
                }

                // 执行动画
                this->cardAnimation(card);
            });
}
// 执行点击后动画
void MainWindow::cardAnimation(Card *card)
{
    int temp; // 插入的地方序号
    Card *temp_card1 = nullptr;
    Card *temp_card2 = nullptr;
    for (int i = 0; i < (sizeof(cardArr) / sizeof(cardArr[0])); i++)
    {
        if (cardArr[i] == nullptr)
        {
            temp = i;
            cardArr[i] = card;
            break;
        }
        else
        {
            if (cardArr[i]->nums != card->nums)
                continue;
            else
            {
                if (cardArr[i + 1] == nullptr || cardArr[i + 1]->nums != card->nums)
                {
                    temp = i + 1;
                    if (cardArr[i + 1] != nullptr)
                    {
                        // 向后移
                        temp_card1 = card;
                        while (cardArr[++i] != nullptr)
                        {
                            // 还有动画在执行
                            if (cardArr[i]->cardAnimation != nullptr)
                            {
                                // 数组下标加一
                                cardArr[i]->arrIndex += 1;
                                cardArr[i]->cardAnimation->stop();
                                cardArr[i]->cardAnimation->setDuration(200);
                                cardArr[i]->cardAnimation->setStartValue(QRect(cardArr[i]->x(), cardArr[i]->y(), cardArr[i]->width(), cardArr[i]->height()));
                                cardArr[i]->cardAnimation->setEndValue(QRect(38 + cardArr[i]->width() * (i + 1), 669, cardArr[i]->width(), cardArr[i]->height()));
                                cardArr[i]->cardAnimation->start();
                            }
                            else
                            {
                                this->cardAnimationRepeat(cardArr[i], cardArr[i]->pos().x() + cardArr[i]->width());
                            }
                            // cardArr[i]->move(cardArr[i]->pos().x() + cardArr[i]->width(), cardArr[i]->pos().y());
                            temp_card2 = cardArr[i];
                            cardArr[i] = temp_card1;
                            temp_card1 = temp_card2;
                        }
                        cardArr[i] = temp_card1;
                    }
                    else
                        cardArr[i + 1] = card;
                    break;
                }
                else
                    continue;
            }
        }
    }
    // 记录数组下标
    card->arrIndex = temp;

    // 创建动态对象
    QPropertyAnimation *animation = new QPropertyAnimation(card, "geometry");
    // 记录动画指针
    card->cardAnimation = animation;
    animation->setParent(card);
    // 设置动画时间
    animation->setDuration(400);
    // 设置起始位置
    animation->setStartValue(QRect(card->x(), card->y(), card->width(), card->height()));
    // 设置结束位置
    animation->setEndValue(QRect(38 + card->width() * temp, 669, card->width(), card->height()));
    // 设置运动曲线
    animation->setEasingCurve(QEasingCurve::OutQuad);
    // 执行动画
    animation->start();

    // 动画结束
    connect(animation, &QPropertyAnimation::finished, [=]()
            {
                card->cardAnimation = nullptr;
                delete animation;

                // 判断是否可以三消 并进行操作
                int del_count = 0;
                Card *del_card1 = nullptr;
                Card *del_card2 = nullptr;
                Card *del_card3 = nullptr;
                for (int i = 0; i < card->arrIndex; i++)
                {
                    if (cardArr[i]->nums == card->nums)
                        del_count++;
                    if (del_count == 2)
                    {
                        this->AllCardNums -= 3;
                        // 删除元素
                        del_card1 = cardArr[i - 1];
                        cardArr[i - 1] = nullptr;
                        del_card2 = cardArr[i];
                        cardArr[i] = nullptr;
                        del_card3 = cardArr[i + 1];
                        cardArr[i + 1] = nullptr;
                        delete del_card1;
                        del_card1 = nullptr;
                        delete del_card2;
                        del_card2 = nullptr;
                        delete del_card3;
                        del_card3 = nullptr;
                        // 并将后面的向前移
                        i += 2;
                        while (cardArr[i] != nullptr)
                        {
                            // 还有动画在执行
                            if (cardArr[i]->cardAnimation != nullptr)
                            {
                                // 数组下标减三
                                cardArr[i]->arrIndex -= 3;
                                cardArr[i]->cardAnimation->stop();
                                cardArr[i]->cardAnimation->setDuration(200);
                                cardArr[i]->cardAnimation->setStartValue(QRect(cardArr[i]->x(), cardArr[i]->y(), cardArr[i]->width(), cardArr[i]->height()));
                                cardArr[i]->cardAnimation->setEndValue(QRect(38 + cardArr[i]->width() * (i - 3), 669, cardArr[i]->width(), cardArr[i]->height()));
                                cardArr[i]->cardAnimation->start();
                            }
                            else
                            {
                                this->cardAnimationRepeat(cardArr[i], cardArr[i]->x() - cardArr[i]->width() * 3);
                            }
                            // cardArr[i]->move(cardArr[i]->x() - cardArr[i]->width() * 3, cardArr[i]->y());
                            cardArr[i - 3] = cardArr[i];
                            cardArr[i] = nullptr;
                            i++;
                        }
                        if (this->AllCardNums == 0)
                        {
                            this->gameOver(1); // 游戏胜利
                        }

                        break;
                    }
                }

                //        for(int i = 0; i < (sizeof(cardArr) / sizeof(cardArr[0])); i++)
                //        {
                //            if(cardArr[i] != nullptr)
                //                qDebug() << cardArr[i];
                //        }
                //        qDebug();
            });
}
// 重新执行动画（平移时）
void MainWindow::cardAnimationRepeat(Card *card, int posXX)
{
    // 创建动态对象
    QPropertyAnimation *animation = new QPropertyAnimation(card, "geometry");
    // 设置动画时间
    animation->setDuration(180);
    // 设置起始位置
    animation->setStartValue(QRect(card->x(), card->y(), card->width(), card->height()));
    // 设置结束位置
    animation->setEndValue(QRect(posXX, 669, card->width(), card->height()));
    // 设置运动曲线
    animation->setEasingCurve(QEasingCurve::OutQuad);
    // 执行动画
    animation->start();

    connect(animation, &QPropertyAnimation::finished, [=]()
            {
                delete animation;
            });
}
// 游戏结束
void MainWindow::gameOver(int isWin)
{
    qDebug() << "游戏结束";
    // 放置标签
    QFont font;
    font.setFamily("华文新魏");
    font.setPointSize(40);
    font.setBold(true);
    label_gameOver = new QLabel(this);
    label_gameOver->setGeometry(0, 0, main_width, main_heigth);
    if (isWin == 0)
        label_gameOver->setText("游戏结束!!!");
    else
        label_gameOver->setText("游戏胜利!!!");
    label_gameOver->setAlignment(Qt::AlignCenter);
    label_gameOver->setFont(font);
    //    label_gameOver->setStyleSheet("QLabel{"
    //                                  "background-color: rgba(0, 0, 0, 0);"
    //                                  "color: rgb(255, 0, 0);"
    //                                  "}");
    label_gameOver->show();
    // 定时器实现背景突出
    label_timer = new QTimer(this);
    label_timer->start(5);
    connect(label_timer, &QTimer::timeout, [=]()
            {
                static int label_count = 0;
                label_count++;
                label_gameOver->setStyleSheet(QString("background-color: rgba(0, 0, 0, %1);"
                                                      "color: rgb(30, 144, 255);")
                                                  .arg(label_count));
                if (label_count == 150)
                    label_timer->stop();
            });
}
// 重写画家事件
void MainWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    // 画背景
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/bk.png");
    painter.drawPixmap(0, 0, this->width(), this->height(), pix);

    // 画栏
    pix.load(":/res/0000.png");
    painter.drawPixmap((main_width - pix.width()) * 0.5, main_heigth - 120, pix.width(), pix.height() + 10, pix);
}
MainWindow::~MainWindow()
{
    delete ui;
}
